home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 2000 #5
/
Amiga Plus CD - 2000 - No. 5.iso
/
Tools
/
Dev
/
FPSE_src
/
dis.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-01-01
|
11KB
|
408 lines
/*
MIPS disassembler
=================
Written by BERO
*/
#include "fpse.h"
static char *regname[32] = {
"zero","at","v0","v1","a0","a1","a2","a3",
"t0","t1","t2","t3","t4","t5","t6","t7",
"s0","s1","s2","s3","s4","s5","s6","s7",
"t8","t9","k0","k1","gp","sp","fp","ra"
};
static char *cop0regname[32] = {
/* from mips 4400 manual
"Index","Random","EntryLo0","EntryLo1","Context","PageMask","Wired","$7",
"BadVAddr","Count","EntryHi","Compare","Status","Cause","EPC","PRId",
"Config","LLAddr","WatchLo","WatchHi","XContext","$21","$22","$23",
"$24","$25","ECC","CacheErr","TagLo","TagHi","ErrorEPC","$31"
*/
"INDEX","RAND","TLBL","BPC","CTXT","BDA","TAR","DCIC",
"BADV","BDAM","TLBH","BPCM","SR","CAUSE","EPC","PRID",
"ERREG","$17","$18","$19","$20","$21","$22","$23",
"$24","$25","$26","$27","$28","$29","$30","$31"
};
static char *cop2cregname[32] = {
"R11R12","R13R21","R22R23","R31R32","R33","TRX","TRY","TRZ",
"L11L12","L13L21","L22L23","L31L32","L33","RBK","GBK","BBK",
"LR1LR2","LR3LG1","LG2LG3","LB1LB2","LB3","RFC","GFC","BFC",
"OFX","OFY","H","DQA","DQB","ZSF3","ZSF4","FLAG"
};
static char *cop2regname[32] = {
"VXY0","VZ0","VXY1","VZ1","VXY2","VZ2","RGB","OTZ",
"IR0","IR1","IR2","IR3","SXY0","SXY1","SXY2","SXYP",
"SZ0","SZ1","SZ2","SZ3","RGB0","RGB1","RGB2","RES1",
"MAC0","MAC1","MAC2","MAC3","IRGB","ORGB","LZCS","LZCR"
};
static char *cregname[32] = {
"$0","$1","$2","$3","$4","$5","$6","$7",
"$8","$9","$10","$11","$12","$13","$14","$15",
"$16","$17","$18","$19","$20","$21","$22","$23",
"$24","$25","$26","$27","$28","$29","$30","$31"
};
static char *nemonic[64] = {
"special","bcond","j","jal","beq","bne","blez","bgtz",
"addi","addiu","slti","sltiu","andi","ori","xori","lui",
"cop0","cop1","cop2","cop3","","","","",
"","","","","","","","",
"lb","lh","lwl","lw","lbu","lhu","lwr","",
"sb","sh","swl","sw","","","swr","",
"lwc0","lwc1","lwc2","lwc3","","","","",
"swc0","swc1","swc2","swc3","","","",""
};
static char *special[64] = {
"sll","","srl","sra","sllv","","srlv","srav",
"jr","jalr","","","syscall","break","","",
"mfhi","mthi","mflo","mtlo","","","","",
"mult","multu","div","divu","","","","",
"add","addu","sub","subu","and","or","xor","nor",
"","","slt","sltu","","","","",
"","","","","","","","",
"","","","","","","",""
};
static char *bcond[32] = {
"bltz","bgez","","","","","","",
"","","","","","","","",
"bltzal","bgezal","","","","","","",
"","","","","","","",""
};
static char *cop[16] = {
"mfc","","cfc","","mtc","","ctc","",
"bc","","","","bc","","",""
};
static char *cop0[32] = {
"","tlbr","tlbwi","","","","tlbwr","",
"tlbp","","","","","","","",
"rfe","","","","","","","",
"","","","","","","",""
};
#define MASK(from,n) (((1<<(n))-1)<<(from))
#define CHECK(a)
#define rdna regname[rdno]
#define rtna regname[rtno]
#define rsna regname[rsno]
int dumpreg = 1;
int rlist[4] = { 0,0,0,0 };
#ifndef MAKEDIS
void watch(int num)
{
int i;
if (num < 0) {
for(i=0;i<32;i++)
printf("%-4s = %08x ",regname[i],(int)reg.r[i]);
printf("\n");
} else printf("%-4s = %08x\n",regname[num],(int)reg.r[num]);
}
void watchcop(int num)
{
int i;
switch (num) {
case 2:
for(i=0;i<32;i++)
printf("%-4s = %08x ",cop2cregname[i],(int)reg.ccr2[i]);
break;
case 3:
for(i=0;i<32;i++)
printf("%-4s = %08x ",cop2regname[i],(int)reg.cpr2[i]);
break;
}
printf("\n");
}
static int reduce(int n)
{
int x,y;
for (x=0;x<n;)
{
if (rlist[x]==0 || rlist[x+1]==rlist[x]) {
for (y=x;y<n;y++) rlist[y] = rlist[y+1];
n--;
} else x++;
}
return n;
}
#endif
#ifdef MAKEDIS
#define DUMPREG(r1,r2,r3)
#else
#define DUMPREG(r1,r2,r3) if (dumpreg) { \
int nreg; \
rlist[0] = r1; \
rlist[1] = r2; \
rlist[2] = r3; \
nreg = reduce(3); \
while (nreg--) \
sprintf(buf,"%s %s=%08x",buf, \
regname[rlist[nreg]], \
(int)reg.r[rlist[nreg]]); \
}
#endif
void disasm(char *buf, UINT32 code, UINT32 addr)
{
int op,func; // ,rs,rt,rd,immS;
if (!code) {
strcpy(buf,"nop");
return;
}
op = code>>26;
/* rs = (code>>21)&31;
rt = (code>>16)&31;
rd = (code>>11)&31;
immS = (short)code;
*/
switch(op){
case SPECIAL:
func = code&63;
switch(func){
case SLL:
case SRL:
case SRA:
CHECK(rsno) /* err */
sprintf(buf,"%-5s %s,%s,%d\t",
special[func],rdna,rtna,(int)((code>>6)&31));
DUMPREG(rdno,rtno,0)
break;
case SLLV:
case SRLV:
case SRAV:
CHECK(code & MASK(6,5)) /* err */
sprintf(buf,"%-5s %s,%s,%s\t",special[func],rdna,rtna,rsna);
DUMPREG(rdno,rtno,rsno)
break;
case JR:
CHECK(code & MASK(6,15)) /* err */
sprintf(buf,"%-5s %s\t\t",special[func],rsna);
DUMPREG(rsno,0,0)
break;
case JALR:
CHECK(code & (MASK(6,5)|MASK(16,5))) /* err */
sprintf(buf,"%-5s %s,%s\t",special[func],rsna,rdna);
DUMPREG(rdno,rsno,0)
break;
case SYSCALL:
case BREAK:
sprintf(buf,"%-5s %08x",special[func],(int)((code>>6)&0xfffff));
break;
case MFHI:
case MFLO:
CHECK(code & (MASK(6,5)|MASK(16,10))) /* err */
sprintf(buf,"%-5s %s\t",special[func],rdna);
DUMPREG(rdno,0,0)
break;
case MTHI:
case MTLO:
CHECK(code & MASK(6,15)) /* err */
sprintf(buf,"%-5s %s\t",special[func],rsna);
DUMPREG(rsno,0,0)
break;
case MULT:
case MULTU:
case DIV:
case DIVU:
CHECK(code & MASK(6,10)) /* error */
sprintf(buf,"%-5s %s,%s\t",special[func],rsna,rtna);
DUMPREG(rsno,rtno,0)
break;
case ADD:
case ADDU:
case SUB:
case SUBU:
case AND:
case OR:
case XOR:
case NOR:
case SLT:
case SLTU:
CHECK(code & MASK(6,5)) /* err */
sprintf(buf,"%-5s %s,%s,%s\t",special[func],rdna,rsna,rtna);
DUMPREG(rdno,rtno,rsno)
break;
default:
strcpy(buf,"unknown special");
break;
}
break;
case BCOND:
sprintf(buf,"%-5s %s,%08x\t",bcond[rtno],rsna,(int)(addr+(immS+1)*4));
DUMPREG(rsno,0,0)
break;
case J:
case JAL:
sprintf(buf,"%-5s %08x",nemonic[op],(int)((addr&0xf0000000)|(code&0x3ffffff)*4));
break;
case BEQ:
case BNE:
sprintf(buf,"%-5s %s,%s,%08x\t",nemonic[op],rsna,rtna,(int)(addr+(immS+1)*4));
DUMPREG(rsno,rtno,0)
break;
case BLEZ:
case BGTZ:
CHECK(rtno) /* err */
sprintf(buf,"%-5s %s,%08x\t",nemonic[op],rsna,(int)(addr+(immS+1)*4));
DUMPREG(rsno,0,0)
break;
case ADDI:
case ADDIU:
case SLTI:
case SLTIU:
case ANDI:
case ORI:
case XORI:
case LUI:
sprintf(buf,"%-5s %s,%s,%d\t# %04x",nemonic[op],rtna,rsna,(int)immS,(int)(code&0xffff));
DUMPREG(rsno,0,0)
break;
case COP0:
if (rsno&0x10) {
CHECK(code && MASK(5,20)) /* err */
sprintf(buf,"%s",cop0[code&31]);
} else {
CHECK(code & MASK(0,11)) /* err */
switch(rsno) {
case MFC:
case MTC:
sprintf(buf,"%s0 %s,%s",cop[rsno],rtna,cop0regname[rdno]);
break;
case CFC:
case CTC:
sprintf(buf,"%s0 %s,%s",cop[rsno],rtna,cregname[rdno]);
break;
}
}
break;
case COP2:
if (rsno&0x10) {
sprintf(buf,"cop%d %08x",op&3,(int)(code&0x1ffffff));
} else {
CHECK(code & MASK(0,11)) /* err */
switch(rsno) {
case MFC:
case MTC:
sprintf(buf,"%s2 %s,%s",cop[rsno],rtna,cop2regname[rdno]);
break;
case CFC:
case CTC:
sprintf(buf,"%s2 %s,%s",cop[rsno],rtna,cop2cregname[rdno]);
break;
}
}
break;
case LB:
case LH:
case LWL:
case LW:
case LBU:
case LHU:
case LWR:
case SB:
case SH:
case SWL:
case SW:
case SWR:
sprintf(buf,"%-5s %s,%d(%s)\t",nemonic[op],rtna,immS,rsna);
DUMPREG(rsno,0,0)
break;
case LWC0:
case SWC0:
sprintf(buf,"%-5s %s,%d(%s)",nemonic[op],cop0regname[rtno],(int)immS,rsna);
break;
case SWC2:
case LWC2:
sprintf(buf,"%-5s %s,%d(%s)",nemonic[op],cop2regname[rtno],(int)immS,rsna);
break;
case LWC1:
case LWC3:
case SWC1:
case SWC3:
sprintf(buf,"%-5s %s,%d(%s)",nemonic[op],cregname[rtno],(int)immS,rsna);
break;
default:
strcpy(buf,"unknown");
break;
}
}
#ifdef MAKEDIS
int main(int argc,char *argv[])
{
FILE *fp;
char *buf,*mem;
UINT32 addr,startaddr,fsize;
int i;
// char inputbuf[256];
EXE_HEADER *head;
char strbuf[256];
fp = fopen(argv[1],"rb");
fseek(fp,0,SEEK_END);
fsize = ftell(fp);
fseek(fp,0,SEEK_SET);
buf = malloc(fsize);
fread(buf,1,fsize,fp);
fclose(fp);
head = (void*)buf;
mem = buf;
if (memcmp(head->id,"PS-X EXE",8)==0) {
startaddr = head->t_addr;
mem+=2048;
} else {
if (argc > 2) sscanf(argv[2],"%x",(int *)(&startaddr));
else startaddr = 0xbfc00000;
}
mem-=startaddr;
addr = startaddr;
for (i=0;i<fsize/4;i++)
{
UINT32 code = *(UINT32 *)(mem+addr);
disasm(strbuf,code,addr);
printf("%08x %08x %s\n",(int)addr,(int)code,strbuf);
addr+=4;
}
/*
while(1) {
for(i=0;i<16;i++) {
u_long code = *(u_long*)(mem+addr);
disasm(strbuf,code,addr);
printf("%08x %08x %s\n",addr,code,strbuf);
addr+=4;
}
printf(">");
gets(inputbuf);
if (strcmp(inputbuf,"q")==0) break;
switch(inputbuf[0]){
case 'a': { char *endp; addr=strtoul(inputbuf+1,&endp,16); }
}
}
*/
return 0;
}
#endif